package org.groovyflow.spring.web

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.groovyflow.interceptor.*
import org.groovyflow.spring.web.InterceptorCache
class StandardInterceptorHandler implements InterceptorHandler{
	private InterceptorLogic interceptorLogic = new RailsStyleInterceptorLogic("before", "skipBefore");
	private doingBefore;
	private InterceptorCache interceptorCache;
	private Object lock = new Object();
	
	public void intercept(Object controller, 
			String methName,
			HttpServletRequest request,
			HttpServletResponse response,
			Object ret){
		List filtersToInvoke = getFiltersFromCache(controller, methName)
		if(filtersToInvoke == null){
			synchronized(lock){
				filtersToInvoke = getFiltersFromCache(controller, methName)
				if(!filtersToInvoke){
					this.interceptorLogic.obj = controller
					this.interceptorLogic.methName = methName	
					try{
						interceptorLogic.findFilters()
						filtersToInvoke = interceptorLogic.filtersToInvoke
						putFiltersInCache(controller, methName, filtersToInvoke)
					}finally{
						interceptorLogic.clearObject();
					}					
				}
			}
		}
		filtersToInvoke.each{
			if(doingBefore)
				controller."$it"(request, response)	
			else
				controller."$it"(request, response, ret)	
		}
	}
	
	public void setInterceptorLogic(InterceptorLogic interceptorLogic){
		this.interceptorLogic = interceptorLogic
	}
	public void setDoingBefore(boolean doingBefore){
		this.doingBefore = doingBefore;
	}
	public void setInterceptorCache(InterceptorCache InterceptorCache){
		this.interceptorCache = InterceptorCache;
	}
	
	def getFiltersFromCache(controller, methName){
		return this.interceptorCache.get(controller, methName, getType());
	}
	
	def putFiltersInCache(controller, methName, filters){
		this.interceptorCache.put(controller, methName, filters, getType())
	}
	
	private String getType(){
		return doingBefore ? InterceptorCache.BEFORE : InterceptorCache.AFTER;
	}
	
}